<template>
  <a-layout>
    <a-layout-sider v-model="collapsed" :trigger="null" collapsible :collapsedWidth="20" width="250" style="color: white;">
      <a-row :hidden="hide_form">
         <h2 style="color:white;">AGV路线配置器</h2>
      </a-row>
      <a-row >
          <a-icon
              class="trigger" :style="{fontSize:'1.2em'}"
              :type="collapsed ? 'menu-unfold' : 'menu-fold'"
              @click="handleTrigger"
          />
        <a-tag :hidden="hide_form">区域：{{regionId}}</a-tag>
        <a-button :hidden="hide_form" type="primary" size="small" @click="clearStatus">清除状态</a-button>
        <a href="/help.html"><a-icon type="info" /></a>
      </a-row>


      <AForm layout="vertical" hide-required-mark  :hidden="hide_form">
        <a-row :gutter="[5,5]" class="subtitle">
          <a-col :span="6">点：</a-col>
          <a-col :span="18"><a-input-number v-model="pointid" style="width: 90px;" @change="changePointId" placeholder="输入编号" /></a-col>
        </a-row>
        <a-row :gutter="[2,2]">
          <a-col :span="6">编号：</a-col>
          <a-col :span="18"><a-input-number v-model="point.id" style="width: 140px;" /></a-col>
        </a-row>
        <a-row :gutter="[2,2]" >
          <a-col :span="6">类型：</a-col>
          <a-col :span="18">
            <a-select v-model="point.type"  style="width: 140px;">
              <a-select-option key="">无</a-select-option>
              <a-select-option v-for="d in pointtypes" :key="d.value">
                {{ d.text }}
              </a-select-option>
            </a-select>
          </a-col>
        </a-row>
        <a-row :gutter="[2,2]" >
          <a-col :span="6">坐标: </a-col>
          <a-col :span="18">
            <a-space>
              <a-input-number v-model="point.x" style="width:60px;"/>
              ,
              <a-input-number v-model="point.y" style="width:60px;" />
            </a-space>
          </a-col>
        </a-row>
        <a-row :gutter="[2,2]" >
          <a-col :span="6">对应点: </a-col>
          <a-col :span="18">
            <a-input-number v-model="point.pairId"  style="width: 140px;" />
          </a-col>
        </a-row>
        <a-row :gutter="[6,6]" >
          <a-col :span="6">标签: </a-col>
          <a-col :span="18">
            <a-input v-model="point.tag" style="width: 140px;"/>
          </a-col>
        </a-row>
        <a-row :gutter="[6,6]" >
          <a-col :span="6">说明: </a-col>
          <a-col :span="18">
            <a-input v-model="point.remark" style="width: 140px;"/>
          </a-col>
        </a-row>
        <a-row :gutter="[6,6]" >
          <a-col :span="6">工序: </a-col>
          <a-col :span="18">
            <a-input-number v-model="point.step" style="width: 140px;" />
          </a-col>
        </a-row>
        <a-row :gutter="[6,6]" >
          <a-col :span="6">
            <a-button type="primary" size="small" @click="toImport">导入</a-button>
          </a-col>
          <a-col :span="6">
            <a-button type="primary" size="small" @click="savePoint">保存</a-button>
          </a-col>
          <a-col :span="6">
            <a-button type="danger" size="small" @click="delPoint">删除</a-button>
          </a-col>
          <a-col :span="6">
            <a-button type="primary" size="small" @click="refreshPoint">刷新</a-button>
          </a-col>
        </a-row>
      </AForm>

    <AForm  layout="vertical" hide-required-mark :hidden="hide_form">
        <a-row :gutter="[5,5]" class="subtitle">
          <a-col :span="6">线：</a-col>
          <a-col :span="18"><a-input-number v-model="routeid" style="width: 90px;" @change="changeRouteId" placeholder="输入编号" /></a-col>
        </a-row>
      <a-row :gutter="[2,2]">
          <a-col :span="6">编号：</a-col>
          <a-col :span="18"><a-input-number v-model="route.id"  style="width: 140px;" /></a-col>
        </a-row>
        <a-row :gutter="[2,2]">
          <a-col :span="6">类型：</a-col>
          <a-col :span="18">
            <a-select mode="tags" v-model="route.type"  style="width: 140px;">
              <a-select-option v-for="d in routetypes" :key="d.value">
                {{ d.text }}
              </a-select-option>
            </a-select>
          </a-col>
        </a-row>
        <a-row :gutter="[2,2]">
          <a-col :span="6">点: </a-col>
          <a-col :span="18">
            <a-space>
              <a-input v-model="route.points" style="width: 140px;"/>
            </a-space>
          </a-col>
        </a-row>
        <a-row :gutter="[2,2]" >
          <a-col :span="6">起止: </a-col>
          <a-col :span="18">
            <a-space>
              <a-input-number v-model="route.startPoint" style="width: 60px;" readonly />
              -
              <a-input-number v-model="route.endPoint" style="width: 60px;" readonly/>
            </a-space>
          </a-col>
        </a-row>
        <a-row :gutter="[6,6]" >
          <a-col :span="6">说明: </a-col>
          <a-col :span="18">
            <a-input v-model="route.remark" style="width: 140px;"/>
          </a-col>
        </a-row>
        <a-row :gutter="[8,0]" >
          <a-space :size="5">
            <a-button type="primary" size="small" @click="saveRouteConfirm">保存</a-button>
            <a-button type="danger" size="small"  @click="delRoute">删除</a-button>
            <a-button type="primary" size="small"  @click="showRouteFile">生成</a-button>
            <a-button type="" size="small" @click="route=[]">清空</a-button>
          </a-space>
        </a-row>
        <a-row :gutter="[8,0]" >
          <a-space :size="5">
            <a-button type="primary" size="small"  @click="downRouteFile2">下载</a-button>
            <a-button type="primary" size="small"  @click="downloadAll">全部下载</a-button>
          </a-space>
        </a-row>
      </AForm>

      <a-row :gutter="[5, 5]" v-if="routes.length>0" :hidden="hide_form">
        <h4 style="color: white;">关联路线：</h4>
        <a-row v-for="r in routes" :key="'route' + r.id" >
          <a-tag :color="r.style.stroke">{{r.id}} [{{r.startPoint}}-{{r.endPoint}}] {{r.remark}}</a-tag>
        </a-row>
      </a-row>

    </a-layout-sider>
    <a-layout-content class="map-container" :style="{overflow: 'visible'}" >
      <svg xmlns="http://www.w3.org/2000/svg" :width="map.width" :height="map.height" id="map" ref="map" :class="map.bgimgCls">
        <polyline v-if="route.pointstr" :points="route.pointstr" :style="route.style" />
        <polyline v-for="r in routes" :key="'r'+r.id"  :points="r.pointstr" :style="r.style" />
        <circle :class="'dot '+ p.cls" v-for="p in points" :key="p.id" r="3" :cx="p.ax" :cy="p.ay" :id="'dot'+p.id" :data-id="p.id" @mouseover="dotHover" @mouseout="dotOut" @click="dotClick"/>
      </svg>
    </a-layout-content>


    <div id="tooltiptext" class="tooltip" style="position: absolute; display:none;background-color: #cccccc;border-radius:5px;padding: 5px;">
      <div class="popover-title">{{tip.title}}</div>
      <div class="popover-content">
        {{tip.content}}
      </div>
    </div>

    <a-modal title="路线文件内容" :visible="visibleModal" :width="800" okText="保存文件" cancelText="取消" @ok="saveRouteFile" @cancel="visibleModal = false">
      <a-textarea v-model="routetext" :style="{height:'200px'}" ></a-textarea>
    </a-modal>

    <a-modal title="点导入" :visible="visibleImport" :width="800" okText="关闭" cancelText="" @ok="visibleImport=false" @cancel="visibleImport=false">
      <upload />
    </a-modal>

  </a-layout>
</template>

<script>
import pointtypes from '../data/pointtypes.json';
import mapsize from '../data/mapsize.json';
import upload from "@/components/upload";
var POINT_SEP = process.env.VUE_APP_POINT_SEP||'-'; //路线中的点的分隔符，默认减号

export default {
  name: 'Map',
  props: {
    mapid: Number
  },
  components:{
    upload,
  },
  data(){
    return{
      regionId: 1, //工序段ID，区域ID
      map:{width:2858,height: 1858,bgimgCls:'bgimg1',offsetX:800,offsetY:1000},
      collapsed: true,
      hide_form: true,
      //查询点、查询线
      pointid: null,
      routeid: null,
      //点
      points:[],
      point:{},
      routes:[], //与当前点相关的路线
      //点导入窗口
      visibleImport: false,
      //路线
      route:{},
      routetext:'',
      //路线文件内容对话框
      visibleModal:false,


      //简单文本tip
      tip: {title:'',content:''},
      //侧边抽屉
      visible_drawer:false,
      confirmLoading: false,
      routetypes:[],
      pointtypes:pointtypes,
      //固钉
      top: 10,
    }
  },
  created() {
    //vue实例创建时执行，早于mounted()
    // let text = this.readFile('/slam_point.csv');
    // console.log(text);
    // this.makePoints(text);
  },
  mounted() {
    console.log('map mounted.')
    let regionId = process.env.VUE_APP_REGION_ID;
    //this.$notification.info({description:`请确保区域${regionId}服务器的adsserver运行.桌面脚本：start_ADS.bat`})
    this.regionId = regionId;
    let mapSize = mapsize[regionId]
    this.map.bgimgCls = `bgimg${regionId}`||'bgimg1'
    this.map.width = mapSize.width
    this.map.height = mapSize.height
    //页面加载完成后执行
    this.queryPoints()
    //加载路线类型
    this.queryRouteTypes()
  },
  methods:{
    toImport(){
      this.visibleImport = true;
    },
    refreshPoint(){
      this.axios.get(`/cache/evict/route*`)
      .then(res=>{
        if(res.status == 200 && res.data.success){
          this.$message.success(res.data.message)
          this.queryPoints()
        }else{
          this.$message.warning("请求失败")
        }
      }).catch(err =>{
        this.$message.error(`刷新失败：${err}`)
      })
    },
    saveRouteConfirm(){
      if(this.route.id){
        let that = this
        this.$confirm({
          title:`按确定修改当前路线`,
          onOk(){
            that.saveRoute()
          }
        })
      }else{
        //添加新路线
        this.saveRoute()
      }
    },
    saveRoute(){
      if(!this.route.points.includes(`-`)){
        this.$message.warning(`路线点位设置错误`)
        return
      }
      this.axios.post(`/route/`, this.route)
          .then(res=>{
            if(res.status == 200){
              if(res.data.success){
                this.route = res.data.data;
                this.$message.success('保存成功')
              }else{
                this.$message.warning(`保存失败:${res.data.message}`)
              }
            }else{
              this.$message.warning('请求异常')
            }
          }).catch(err=>{
        console.error(err)
        this.$message.error(`保存错误:${err}`)
      })
    },
    delRoute(){
      if(!this.route.id){
        this.$message.warning("没有指定路线或当前路线未保存")
        return
      }
      var url = `/route/${this.route.id}`;
      var that = this;
      this.$confirm({title:"按确定删除路线，请慎重操作！！",
        onOk(){
          that.axios.delete(url)
              .then(res=>{
                if(res.status == 200){
                  if(res.data.success){
                    that.$message.success("删除成功");
                    that.route = {};
                  }else{
                    that.$message.warning("删除失败:" + res.data.message)
                  }
                } else{
                  that.$message.error("删除异常：" +res.data);
                }
              }).catch(e=>{
            console.error(e);
          })
        }
      })
    },
    savePoint(){
      this.axios.post(`/point/`, this.point)
      .then(res=>{
        if(res.status==200){
          this.$message.success("保存成功")
        }else{
          this.$message.warning("保存失败")
        }
      }).catch(err=>{console.log(err);this.$message.error(err);})
    },
    delPoint(){
      let pid = this.point.id;
      var url = `/point/${pid}`;
      var that = this;
      this.$confirm({title:"按确定删除点。请务必慎重！慎重！慎重！！！",
        onOk(){
          that.axios.delete(url)
              .then(res=>{
                if(res.status == 200){
                  if(res.data.success){
                    that.$message.success("删除成功");
                    let i = that.points.findIndex(p=>p.id == pid);
                    that.points.splice(i, 1);
                    that.point = {};
                  }else{
                    that.$message.warning("删除失败:" + res.data.message)
                  }
                } else{
                  that.$message.error("删除异常：" +res.data);
                }
              }).catch(e=>{
            console.error(e);
          })
        }
      })
    },
    showRouteFile(){
      if(!this.route.id){
        this.$message.warning("没有指定路线或当前路线未保存")
      }
      this.visibleModal = true
      let route = this.route
      let arr = route.points.split(POINT_SEP)
      if(arr.length<2){
        this.$notification.warn({message:'提示',description:'点数少于2个'})
        return
      }
      //终点类型
      let point = this.points.find(p=>p.id+''==arr[arr.length-1])
      let text = `routeNum,fun,,\r\n`
      if(1==point.type||2==point.type){//机台入口，充电入口
        text += `${route.id},1,,\r\n`
      }else{
        text += `${route.id},0,,\r\n`
      }
      text += `start,end,dir,turn\r\n`
      for(var i=0;i<arr.length-1;i++){
        if(i<arr.length-2){
          text += `${arr[i]},${arr[i+1]},1,0\r\n`
        }else{//最后一行转弯采用直角
          text += `${arr[i]},${arr[i+1]},1,1\r\n`
        }
      }
      // this.routetext = text.replaceAll(',','\t')
      this.routetext = text
    },
    saveRouteFile(){
      this.axios.post(`/route/saveFile/${this.route.id}`, {content: this.routetext})
          .then(res=>{
            if(res.status == 200){
              this.$message.success('保存路线文件成功')
              //window.open(`/route/download/${this.route.id}`,'_blank')
            }else{
              this.$message.warning('保存文本内容失败')
            }
          }).catch(e=>{
        if(e.request.status >= 500){
          this.$message.error(`保存文件内容失败异常`)
        }else{
          this.$message.error(e.message)
        }
      })
    },
    downRouteFile1(){
      if(!this.route.id){
        this.$message.warning("没有指定路线或当前路线未保存")
        return
      }
      this.axios.post(`/route/file/${this.route.id}`, {content: this.routetext})
      .then(res=>{
        if(res.status == 200){
          this.$message.success('保存路线文件成功')
          window.open(`/route/file/${this.route.id}`,'_blank')
        }else{
          this.$message.warning('保存文本内容失败')
        }
      }).catch(e=>{
        if(e.request.status >= 500){
          this.$message.error(`保存文件内容失败异常`)
        }else{
          this.$message.error(e.message)
        }
      })
    },
    downRouteFile2(){
      window.open(`/route/file/${this.route.id}`,'_blank');
    },
    downloadAll(){
      this.$message.info('coming...')
    },
    dotHover(evt){
      console.log(evt.target.dataset.id)
      let point = this.points.filter(p=>p.id == evt.target.dataset.id)[0]
      this.tip.title = `点：${point.id}`
      this.tip.content = `激光坐标: (${point.x}, ${point.y})`
      this.showSimpleTip(evt)
      //显示此点相关的路线
      this.queryRelatedRoutes(point.id);
    },
    dotOut(){
      // console.log(evt.target.dataset.id)
      this.hideSimpleTip()
      //清空相关路线
      this.routes = []
    },
    dotClick(evt){
      this.showSider()
      let pid = evt.target.dataset.id
      //显示点详情
      this.point = this.points.filter(p=>p.id == pid)[0]
      if(this.point.cls=='focus'){
        this.point.cls = 'origin'
      }else{
        this.point.cls = 'focus'
      }
      // 添加到路线
      let points = this.route.points
      if(points){
        if(points.startsWith(`${pid}-`)){
          this.route.points = points.replace(`${pid}-`, ``)
        }else if(points.endsWith(`-${pid}`)){
          this.route.points = points.replace(`-${pid}`, ``)
        }else if(points.indexOf(pid) != -1){
          this.route.points = points.replace(`-${pid}-`, `-`)
        }else{
          this.route.points = `${points}-${pid}`
        }
        this.makeRouteData(this.route)
      }else{
        this.route.points = pid;
      }
    },
    clearStatus(){
      this.dotOut()
      this.points.forEach(p=>{if(p.cls=='focus')p.cls='origin';})
    },
    makeRouteData(route){
      //console.log(route)
      //生成pointstr，cls,statePoint,endPoint
      let pids = route.points.split(POINT_SEP)
      if(pids.length>1){
        route.startPoint = pids[0]
        route.endPoint = pids[pids.length-1]
        route.style = this.makeRandomRouteStyle()
        route.pointstr = this.makePolylinePoints(route)
      }
      return route
    },
    makeRandomRouteStyle(){
      return {"stroke":`rgb(${this.randomColor()}, ${this.randomColor()}, ${this.randomColor()})`, "stroke-width":'3px'}
    },
    randomColor(){
      return (Math.random() * 1000 % 255).toFixed()
    },
    //生成路线点的折线点坐标数据
    makePolylinePoints(route){
      let pids = route.points.split(POINT_SEP)
      // let points = pids.map(pid=>this.points.filter(p=>p.id+''==pid)[0]) // 旧版数据中大量无效点,导致出出
      let points = []
      let notexits = []
      pids.forEach(pid=>{
        let arr = this.points.filter(p=>p.id+''==pid)
        if(arr.length){
          points.push(arr[0])
        }else{
          notexits.push(pid)
        }
      })
      if(notexits.length){
        console.log(notexits)
        this.$notification.error({message:`路线${route.id}上不存在的点`, description: notexits.join(',')})
      }
      return points.map(p=>`${p.ax}, ${p.ay}`).join(' ')
    },
    showSimpleTip(evt){
      let tooltip = document.getElementById("tooltiptext");
      tooltip.style.display = "block";
      // console.log(evt.pageX, evt.clientX, evt.screenX)
      // console.log(window.innerWidth, window.outerWidth, window.pageXOffset)
      let pagex = (evt.pageX + 5 + 200)> window.innerWidth ? (evt.pageX - 160):(evt.pageX + 5);
      let pagey = (evt.pageY + 5 + 50)> window.innerHeight ? (evt.pageY - 60):(evt.pageY + 5);
      // console.log(pagex, pagey);
      tooltip.style.left = pagex + 'px';
      tooltip.style.top = pagey + 'px';
    },
    hideSimpleTip(){
      var tooltip = document.getElementById("tooltiptext");
      tooltip.style.display = "none";
    },
    queryRelatedRoutes(pid){
      //todo 查询点相关的路线,并生成pointstr,cls，样式采用随机色，以区别不同线
      this.axios.get(`/route/bypoint/${pid}`)
          .then(res=>{
            if(res.status==200){
              if(res.data){
                res.data.forEach(r=>this.makeRouteData(r))
                this.routes = res.data
              }else{
                this.$message.warning(`查询异常`)
              }
            }else{
              this.$message.warning(`请求异常`)
            }
          }).catch(err=>console.error(err))
    },
    queryPoints(){
      // var data = this.mockData();
      // this.points = data;
      this.axios.get(`/point/`)
      .then(res=>{
        if(res.status == 200){
          let data = res.data
          data.push({id:9999, x:0, y:0, type:0, cls:'origin'})
          this.points = this.makeAllPointsData(data);
        }else{
          this.$message.warning(`查询异常`)
        }
      }).catch(e=>{
        if(e.request.status >= 500){
          this.$message.error(`请求数据异常。请检查应用服务是否启动`)
        }else{
          this.$message.error(e.message)
        }
      })
    },
    queryRouteTypes(){
      this.axios.get(`/route/types`)
      .then(res=>{
        if(res.status == 200){
          this.routetypes = res.data.map(v=>{return {value:v,text:v}})
          // this.routetypes = res.data
        }else{
          this.$message.warning(`查询异常`)
        }
      }).catch(e=>{
        if(e.request.status >= 500){
          this.$message.error(`请求数据异常。请检查应用服务是否启动`)
        }else{
          this.$message.error(e.message)
        }
      })
    },

    makeAllPointsData(data){
      return data.map(p=>{
        let xy = this.makeScreenPoint(p.x, p.y)
        p['ax'] = xy[0]
        p['ay'] = xy[1]
        return p
      })
    },
    //转换为屏幕坐标
    makeScreenPoint(x, y){
      switch (this.regionId) {
        case '1':
          return [x/50 + 1010, -y/50 + 1105]; // bgimg放在svg上时
          // return [x/50 + 1010, -y/50 + 1105]; //bgimg类放在父容器时 （注：存在问题是，当缩小67%时，点位发生偏移）
        case '2':
          return [-x/50 + 450, y/50 + 920];// bgimg放在svg上时
          // return [-x/50 + 200, y/50 + 940]; //bgimg类放在父容器时
        case '3':
          return [-x/50 + 1570, y/50 + 1770 ]; //bgimg放在svg上时
          // return [-(x-78000)/50, (y+89000)/50];  //bgimg类放在父容器时（先位移，再缩放）
          // return [-x/50 + 1560, y/50 + 1780 ]; //bgimg类放在父容器时（先绽放，再位移）
        case '4':
          return [x/5 + 1010, -y/5 + 1105];
        default:
          return [x/5 + 1010, -y/5 + 1105];
      }
    },
    mockData(){
      return [
        {id:1,ax:100,ay:100,x:12333, y:9223},
        {id:2,ax:200,ay:200,x:323, y:2222},
        {id:3,ax:300,ay:300,x:3323, y:8344},
      ]
    },
    handleCancel(){
      this.visible_drawer = false
    },
    handleOk(){
      this.confirmLoading = true;
      setTimeout(() => {
        this.visible = false;
        this.confirmLoading = false;
      }, 2000);
    },
    handleTrigger(){
      this.collapsed = !this.collapsed;
      this.hide_form = !this.hide_form;
    },
    showSider(){
      this.collapsed = false;
      this.hide_form = false;
    },
    hideSider(){
      this.collapsed = true;
      this.hide_form = true;
    },
    changePointId(id){
      let arr = this.points.filter(p=>p.id == id)
      if(arr.length>0){
        this.point = arr[0]
        this.point.cls = 'focus'
      }else{
        this.$notification.warn({message:"提示", description:"没有此点"})
      }
    },
    changeRouteId(id){
      this.axios.get(`/route/${id}`)
      .then(res=>{
        if(res.status==200){
          if(res.data){
            this.route = this.makeRouteData(res.data);
          }else{
            this.$message.warning(`路线${id}不存在`)
          }
        }else{
          this.$message.warning(`查询异常`)
        }
      }).catch(err=>console.error(err))
    },
    pressEnterRouteId(e){
      console.log(e.target.value);
    },
    readFile(filePath) {
      // 创建一个新的xhr对象
      let xhr = null
      if (window.XMLHttpRequest) {
        xhr = new XMLHttpRequest()
      } else {
        // eslint-disable-next-line
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
      }
      const okStatus = document.location.protocol === 'file' ? 0 : 200
      xhr.open('GET', filePath, false)
      xhr.overrideMimeType('text/html;charset=utf-8')
      xhr.send(null)
      return xhr.status === okStatus ? xhr.responseText : null
    },
    makePoints(text){
      let arr = text.split('\r\n')
      arr.splice(0,1) //第一行为列名id,x,y，去掉
      arr.splice(arr.length-1,1) //最后一行空行，去掉
      console.log(`共有点：`, arr.length)
      let points = arr.map(s=>{
        if(s.length==0) return null;
        let r = s.split(',')
        let ax = r[1]/25 + 0
        let ay = -r[2]/25
        // return {keys[0]:r[0], keys[1]:r[1],keys[2]:r[2], "ax":ax, "ay": ay}
        return {"id":r[0], "x":r[1],"y":r[2], "ax":ax, "ay": ay}
      })
      console.log(points)
      this.points = points;
    },
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss">
@import "../assets/scss/style";
@import "../assets/scss/map_bright";

/*更改ant-asider中的文字颜色*/
.ant-row{
  color: white;
}
.ant-input-*{
  color: black;
}
/*输入框样式*/

/*修改左侧：浮动固定*/
.ant-layout-sider-children {
  float: left;
  display: block;
  position: fixed;
  left: 0px;
  top: 0px;
  background-color: black;
}
.subtitle{
  background-color:darkblue;margin: 5px 5px 0 0;
}
.subtitle > div:first-child{
  font-size: 1.2em;font-width: bold;
}
.subtitle input{
  background-color:beige;
}
</style>
